/**
 * 描述:项目总结（新）
 *
 * 1.预约服务设计，基于nginx构建分布式服务，负载均衡与限流，引入redis做库存预热，mq做服务异步削峰，解决大流量预约卡顿问题
 *      1.最初业务流程：同步预约，接口限流 + 数据库CAS扣减库存
 *          1.流程：登录信息验证 -> 校验预约数据合法性 -> 判断是否重复预约 -> 调用三个接口,请求身份认证数据 -> 通过接口数据身份认证与预约资格确认 ->
 *          扣减预约库存(通过mysql CAS的方式) -> 存入预约数据 -> 预约人员存入redis -> 异步发送短信 -> 返回预约成功
 *          2.解决超约问题：
 *              1.扣减库存的时候通过mysql的CAS来保证的，update appointment_stock set stock = stock - 1 where stock >= 1 and id = #{stockId}
 *          3.问题：
 *              1.1000并发的测试，两台机器，吞吐量较低，两台服务器，qps很低，原因是三个接口的调用花费的时长太长
 *              2.限流之后只有少部分的人进来，要对小部分的人做判重，但是业务上只允许预约一次，每次都是那部分人进来预约导致大部分人被返回服务器繁忙
 *              3.业务吞吐量太低，在身份校验那边耗时较长，而且不能做到立刻减库存，与预约成功，用户体验也差，一直返回系统繁忙
 *              4.随着压力测试不断加大，系统的滞留连接数也不断增加，逐渐出现超时连接的错误，所以必须将请求在一个地方先打回，采用redis扣减库存
 *      2.升级后的业务流程：异步预约，redis扣减库存 + mq削峰 + 客户端异步获取预约结果的方案
 *          1.流程：
 *              1.登录信息验证 -> 校验预约数据合法性 -> 扣减预约库存(通过redis库存预热，扣减，用lua脚本保证原子性) -> 发送消息到mq（
 *                调用三个接口,请求身份认证数据 ->
 *                通过接口数据身份认证与预约资格确认 -> 认证失败的话返回认证失败，并且redis库存+1 -> 存入预约数据 -> 预约人员存入redis
 *                -> 异步发送短信） -> 返回预约成功
 *              2.前端对一个接口进行短轮询，每隔2s发起一次，如果查询到key，则代表预约成功，查询3次后，自动失败
 *          2.解决超约问题：
 *              1.使用分布式锁redission，锁住扣减和查询数量判断是否大于0的代码
 *              2.使用lua脚本保证扣减的原子性
 *          3.问题：
 *              1.不知道怎么压测的，反正测试说是6000，因为是异步的，也不太好测，但是在扣减库存与判断预约这一层，是不存在什么问题的
 *              2.两台服务器两千五并发不出现异常
 *              3.redis层处理的速度很快，但是到接口调用层就非常慢，导致qps一直上不去，所以引入mq
 *              4.使用的是lua脚本保证扣减库存的原子性，一方面是因为分布式锁有锁的开销，并且会产生锁的各种问题,在并发量比较低的时候，使用是没有问题的
 *      3.限流方案
 *          1.nginx限流
 *              1.控制速率的限流 limit_req_zone，限制1s内每个ip的访问次数为1次，解决一些类似黄牛的人，会用脚本去请求，在还没开始预约的时候，就会在日志中发现有用脚本刷的.
 *                nginx的限流是基于毫秒的，如果是2r/s，在0-500ms的时候允许一个请求，在500-1000ms的时候允许另一个
 *              2.控制并发数 limit_conn_zone 和 limit_conn，限制单个ip的请求数，这个请求数是指服务器已经处理了这个请求，但是还没返回值并且断开连接的请求总的数量
 *          2.服务端限流：guava RateLimiter，实现对接口方法限流，利用一个concurrentHashMap将每个方法的请求数量记录起来。将qps统一分配，均摊qps到每台服务器中，因为nginx采用的默认轮询方式负载均很，也可以做到平均分配。但是如果服务器的
 *            配置不同，平均分配容易出现服务器资源不均的情况，还是需要nginx进行权重配置
 *          3.分布式限流：redission实现的一个限流算法，每取一次令牌都会进行一次网络开销，网络开销起码是毫秒级别的，支持的并发量非常有限
 *          4.网关限流：gateway限流，redis+lua，实现对IP限流
 *      4.接口超时重试机制：
 *          1.基于guava-retry写的，自定义超时次数和等待策略，自定义超时重试超过阈值后的处理
 *          2.RestTemplate自定义超时时间，获取不到结果重试一次，在catch中重试一次
 *      5.关于参数的一些可能会问的问题
 *          1.系统的qps是多少：一开始系统是单服务的，没有做分布式，也没有做业务升级，qps在三百多左右。后面做了升级，并且部了三台服务器，qps在4000左右，峰值是5000多。单机redis用
 *            sentinel测试的时候，只走redis + lua能达到8000左右
 *          2.一次活动有多少人预约：加起来预约的总人数没统计过，单次活动的话是有统计进来用户数，最高是在20000左右（用redis的bitmap统计的）
 *          3.每次开放多少个预约名额：每次的数量不一样，差不多一千左右吧，分不同时段，时段是政府给社区发放口罩的时间，每个时段一两百人这样
 *          4.你在这个系统中充当什么角色？主要负责什么？我们一整个小组，5个人，有一个技术经理带，业务其实不难，主要是大家一起讨论方案，适配系统，然后配合测试压测啥的。
 *            guava限流代码是我写的，redis lua指令是我提出来的，异步预约的方案是技术经理选的，kafka的环境是我搭建的，然后还有一些接口调用超时重试啥的代码
 *          5.系统的所要达到的目标是啥：当时政府放出去的一个公众号的预约的公告，也是我们做的，那个页面的浏览量大致两万多左右，然后项目经理说qps尽量达到5000这样吧，
 *            而且要控制接口成功预约返回在2s内，因为中间有调第三方接口，要1s左右，最终测试说四千多。后面问了说能不能做成异步预约的，可以先给用户返回一个正在预约中的信息，
 *            然后前端异步获取是否成功
 *          6.线上有没优化什么：
 *              1.数据库是原先就是集群，而且有做限流，或者直接打到redis上返回，真正进到业务内部，需要操作数据库的并发量并不高，所以没有出现啥问题
 *              2.jvm是采用了G1的垃圾回收器，堆大小是16g，单机的时候，并发量上去，jmater会出现connection reset的错误连接，初步推测是系统的连接数滞留的太多，
 *                因为内部有调用第三方接口比较慢，有开启linux的端口重用和将文件句柄数加大到了65535。但是单机还是扛不住，异步预约的吞吐量只能平衡在1200多，
 *                所以用nginx搞个负载，布了三台服务器
 *      6.优化：
 *          1.
 * 2.文章展示模块，redis数据过期机制，构建热点管理，文章点赞排行功能
 *      1.缓存列表查询，从zsort中查询出查询desc排列的id，然后数据库in一下id查询出文章标题和id，然后拼接点赞数量
 *      2.点赞功能，zsort的key incry 1
 *      3.取消点赞功能，zsort的 incry -1
 * 3.XJ项目技术负责人，负责评估客户需求，分配研发任务，构建项目底层框架。解决了单表亿级数据存储入库与统计分析缓慢的问题
 *      1.这些数据是什么数据
 *          1.这是银行账单转账的数据，有四张表，有3张表的数据都接近4亿，这些数据，是客户通过文件的方式传给我们，我们需要将这些数据解析入库，
 *            并关联出案件，做到能实时统计各个案件的流水金额，流水次数等等
 *      2.你是如何存储这些数据的
 *          1.mysql单表存储，这个是最先被pass的方案，曾经是有听说过，mysql单表存储数据超过两千万行的时候，查询性能将会严重下降。而且将4亿条数据直接存储到一张表上，确实不切实际
 *          2.所以我们是考虑了分库分表。阿里巴巴java开发手册中也指出，mysql存储数据超过500万或者单表容量超过2g的时候，则需要考虑分表。如果将银行卡号进行取模分表，也是可以的。
 *            但是如果按照案件的纬度去查询数据，难以做到优化。还有个问题摆在面前，如果1000万一张，单表4亿需要起码分出40张表。而且每日新增的数据量巨大，需要经常自动或者手动的扩容。
 *            所以这个方案暂时搁置
 *          3.第三个方案是，hbase和elasticsearch构建二级索引，不采用sql方式查询数据，存储超亿级的数据时性能很好,将数据存入hbase再通过kafka推送至elasticsearch存储入关键的索引字段，
 *            可以做到索引查询的毫秒级别的响应。但是，es到达60万数据以上就会逐渐失去精度，如果是做流水的统计的话，需要精确的数据，而且es数据入库的速度太慢，数据一致性很难保证，
 *            所以pass
 *          4.第四个方案是大数据分析库，有两种选择，一种我们自己搭建一套doris集群（一个数仓的中间件），成本太大，还有用阿里云ads mysql2.0，正好当时有应用到，支持数据修改，分页查询，
 *            插入速度经测试达到10万/s。针对多维度的大屏统计是做了离线数据计算，用分布式调度工具定时执行聚合统计后存到redis中，根据业务制定刷新时间。对于实时的统计查询，
 *            采用物化视图的方式，根据插入数据不断更新统计。至于单条的数据查询与分页查询，也是完全支持的
 *      3.你的团队有多少个人？如何负责的
 *          1.三个人，我们部门是这样，每个研发或多或少带一个主要负责项目，另外有一个前端一两个后端会参与开发，组成小组，技术负责人主要是负责解决一些技术难点或者技术选型的问题，
 *            还有根据项目经理的需求分配研发的任务，实在不会主动咨询技术经理或者查阅资料，也是一种内部的培养方式
 *      4.底层框架是怎样的？你如何构建
 *          1.项目框架目前是有两套，一套是springcloud，nacos注册中心，gateway网关为基础的低代码开发框架，另一套是早期基于dubbo的rpc框架，现在基本上都是用springcloud那套了。
 *            然后我们会根据项目的体量大小，和业务复杂度，预先估计出项目所用到的中间件，服务器容量，以及项目整体框架是基于单体应用还是微服务分布式部署。
 *            框架中已经把所有的用户登录，系统管理都做好了，只需要做一些业务上的改造，然后根据项目设计书描述的功能，进行需求分解并且开发
 *          2.新的回答：
 *              1.
 * @author Madison You
 * @created 20:07
 */
public class ProjectNew {
}
